package cn.itsource.pethome.user.service.impl;

import cn.itsource.pethome.basic.constant.PetHomeConstant;
import cn.itsource.pethome.basic.util.HttpClientUtils;
import cn.itsource.pethome.basic.util.MD5Utils;
import cn.itsource.pethome.basic.util.StrUtils;
import cn.itsource.pethome.user.domain.LoginInfo;
import cn.itsource.pethome.user.domain.User;
import cn.itsource.pethome.user.domain.WechatUser;
import cn.itsource.pethome.user.domain.dto.UserDto;
import cn.itsource.pethome.user.mapper.LoginInfoMapper;
import cn.itsource.pethome.user.mapper.UserMapper;
import cn.itsource.pethome.user.mapper.WechatMapper;
import cn.itsource.pethome.user.service.IWechatService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WechatServiceImpl implements IWechatService {
    @Autowired(required = false)
    private WechatMapper wechatMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired(required = false)
    private LoginInfoMapper loginInfoMapper;
    @Autowired(required = false)
    private UserMapper userMapper;



    @Override
    public Map<String, Object> handleCallBack(String code) {
        //获取tokenurl地址
        String tokenUrl = PetHomeConstant.TOKENURL.replace("APPID", PetHomeConstant.APPID)
                        .replace("SECRET",PetHomeConstant.SECRET )
                        .replace("CODE",code );
        //使用java程序发送get请求，它就会返回json格式
        String tokenJsonStr  = HttpClientUtils.httpGet(tokenUrl);
        //把json字符串转为json对象
        JSONObject jsonObject = JSONObject.parseObject(tokenJsonStr);
        //微信用户唯一标志
        String openid = jsonObject.getString("openid");
        //获取token的值
        String access_token  = jsonObject.getString("access_token");
        //已获得授权出现此字段
        String unionid = (String)jsonObject.get("unionid");
        //通过token获取资源
        String userInfoUrl = PetHomeConstant.USERINFOURL.replace("ACCESS_TOKEN", access_token)
                .replace("OPENID", openid);
        //获取微信用户基本信息
        String userInfoJsonStr  = HttpClientUtils.httpGet(userInfoUrl);
        //把json字符串转为json对象
         jsonObject = JSONObject.parseObject(userInfoJsonStr);
         //通过openid唯一标志在微信用户表中查找是否有对应的数据
        WechatUser wechatUser = wechatMapper.loadByOpenid(openid);
        //创建map集合封装数据拿到前端
        Map<String, Object> map = new HashMap<>();
        //如果对象为空，就证明，当前用户和微信还没有绑定
        if(wechatUser==null){
            WechatUser user = new WechatUser();
            user.setOpenid(openid);
            user.setNickname(jsonObject.getString("nickname"));
            user.setSex(jsonObject.getBoolean("sex"));
            //头像
            user.setHeadimgurl(jsonObject.getString("headimgurl"));
            //授权之后唯一标志
            user.setUnionid(unionid);
            user.setAddress(jsonObject.getString("province")+""+jsonObject.getString("city"));
            //将user对象保存起来
            wechatMapper.save(user);
            //跳转到绑定界面
            map.put("openid",openid );
            return map;
        }else {
            LoginInfo loginInfo = wechatUser.getLoginInfo();
            if(loginInfo==null){
                //跳转到绑定界面
                map.put("openid",openid );
                return map;
            }else {
                //随机创建token
                String token = UUID.randomUUID().toString();
                //直接登录
                redisTemplate.opsForValue().set(token,loginInfo, 30, TimeUnit.MINUTES);
                map.put("token",token );
                map.put("loginUser",loginInfo );
                return map;

            }
        }

        }

    @Override
    public Map<String, Object> binder(UserDto userDto) {
        //校验数据
        checkUserDto(userDto);
        //设置username，方便sql语句查询数据
        userDto.setUsername(userDto.getPhone());
        //判断手机号码是否在数据库中已存在
        LoginInfo loginInfo = loginInfoMapper.loadByUserDto(userDto);
        //创建map集合，封装登录信息和token信息
        Map<String, Object> map = new HashMap<>();
        //如果loginInfo为空，就证明之前没有注册该手机账号
        if(loginInfo == null){
            //临时对象转为LoginInfo
            loginInfo = userDto2LoginInfo(userDto);
            //保存LoginInfo
            loginInfoMapper.save(loginInfo);
            //loginInfo2User
            User user = loginInfo2User(loginInfo);
            //保存user对象
            userMapper.save(user);
        }
        //微信和用户绑定一起（修改t_wxuser表）
        wechatMapper.binder(loginInfo.getId(), userDto.getOpenid());
        //直接登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, loginInfo, 30, TimeUnit.MINUTES);
        map.put("token", token);
        map.put("loginUser", loginInfo);
        return map;

    }

    //把登录基本信息转为user对象

    private User loginInfo2User(LoginInfo loginInfo) {
        User user = new User();
        BeanUtils.copyProperties(loginInfo, user);
        user.setState(PetHomeConstant.OK);
        user.setLoginInfo(loginInfo);
        return user;
    }

    private LoginInfo userDto2LoginInfo(UserDto userDto) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setPhone(userDto.getPhone());
        loginInfo.setUsername(userDto.getPhone());
        loginInfo.setType(userDto.getType());
        loginInfo.setSalt(StrUtils.getComplexRandomString(10));
        loginInfo.setPassword(MD5Utils.encrypByMd5(loginInfo.getPhone()+loginInfo.getSalt()));
        return loginInfo;

    }

    private void checkUserDto(UserDto userDto) {
        if(StringUtils.isEmpty(userDto.getPhone())||StringUtils.isEmpty(userDto.getCode())
                ||userDto.getType()==null){
            throw new RuntimeException("请输入完整信息!!");
        }
        //435g:324234234242342
        String codeValue = (String) redisTemplate.opsForValue().get(PetHomeConstant.BINDER_VERIFICATION_CODE + ":" + userDto.getPhone());
        if(StringUtils.isEmpty(codeValue)){
            throw new RuntimeException("验证码已过期!!");
        }
        if(!codeValue.split(":")[0].toLowerCase().equals(userDto.getCode().toLowerCase())){
            throw new RuntimeException("验证码错误!!");
        }
    }
}
